package com.hex.ds.hdrs.engine.exec;

import cn.hutool.core.util.StrUtil;
import com.hex.ds.hdrs.center.service.CenterManager;
import com.hex.ds.hdrs.common.constant.Const;
import com.hex.ds.hdrs.common.exception.BizException;
import com.hex.ds.hdrs.common.utils.HdrsDateUtil;
import com.hex.ds.hdrs.engine.manager.LstFinishManager;
import com.hex.ds.hdrs.engine.manager.ToDoManager;
import com.hex.ds.hdrs.engine.service.DispatcherService;
import com.hex.ds.hdrs.engine.service.LoaderService;
import com.hex.ds.hdrs.engine.service.ProcessorService;
import com.hex.ds.hdrs.period.job.po.JobTask;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * @Package: com.hex.ds.hdrs.engine.exec
 * @ClassName LoaderExec
 * @Description: 加载器执行
 * @Author: jd.chen
 * @Date 2021/7/5 19:11
 * @Version v1.0
 **/
@Slf4j
@EnableScheduling
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class LoaderExec {

    private final CenterManager centerManager;
    private final LoaderService loaderService;
    private final DispatcherService dispatcherService;
    private final ProcessorService processorService;
    private final ToDoManager toDoManager;
    private final LstFinishManager lstFinishManager;

    /**
     * 增量
     */
    @Scheduled(fixedDelayString = "${scheduled.loader.addFixedDelay}", initialDelayString = "${scheduled.loader.addInitialDelay}")
    private void addExec() {
        log.debug("【LoaderExec.addExec】加载器执行增量开始===》【{}】", HdrsDateUtil.getCurTs());
        if (!this.isCanLoad(Const.ADD_LOADER_MARK)) {
            return;
        }
        try {
            this.addDeal();
        } catch (Exception e) {
            log.error("【LoaderService.add】加载器--增量【异常】:{}", e.getMessage(), e);
        } finally {
            this.finalDeal();
            log.debug("【LoaderService.add】加载器--增量结束【{}】", HdrsDateUtil.getCurTs());
        }
    }

    /**
     * 全量
     */
    @Scheduled(fixedDelayString = "${scheduled.loader.allFixedDelay}", initialDelayString = "${scheduled.loader.allInitialDelay}")
    private void allExec() {
        log.info("【LoaderExec.allExec】加载器执行全量开始===》【{}】", HdrsDateUtil.getCurTs());
        if (!this.isCanLoad(Const.ALL_LOADER_MARK)) {
            return;
        }
        try {
            this.allDeal();
        } catch (Exception e) {
            log.error("【LoaderService.all】加载器--全量【异常】:{}", e.getMessage(), e);
        } finally {
            this.finalDeal();
            log.info("【LoaderService.all】结束加载器--全量【{}】", HdrsDateUtil.getCurTs());
        }
    }

    /**
     * 是否可加载
     *
     * @return
     */
    public boolean isCanLoad(String mark) {
        log.debug("加载器是否可加载【LoaderExec.isCanLoad】=======》");
        if (!centerManager.isCanDeal()) {
            log.warn("【该中心不是Master】");
            return false;
        }
        if (!toDoManager.loaderMark(mark)) {
            log.warn("【加载器正忙或未初始化成功】");
            return false;
        }
        return true;
    }

    /**
     * 增量或全量  finally所需处理
     */
    public void finalDeal() {
        log.debug("【finalDeal】增量或全量释放资源==========》");
        try {
            if (StrUtil.equalsAnyIgnoreCase(toDoManager.getMark(),Const.ALL_LOADER_MARK)) {
                //1. 清空delta
                toDoManager.clearDeltaAppJobList();
                //2. 清空delta
                lstFinishManager.clearDeltaJobList();
            }
            //3. 更新最新查询时间
            toDoManager.setLastQryTs(toDoManager.getCurQryTs());
            //4. 分发器启用
            this.dispatcherService.continueDispatcher();
            //5. 处理器启用
            this.processorService.continueProcess();
            //6. 恢复打标
            toDoManager.setMark(Const.FREE_LOADER_MARK);
        } catch (Exception e) {
            log.error("【finalDeal】增量或全量释放资源异常: {}", e.getMessage(), e);
        }
    }

    /**
     * 增量处理
     */
    private void addDeal() {
        log.debug("【LoaderExec.addExec】获取数据库待处理队列--开始");
        List<JobTask> addJobTaskList = this.loaderService.getAddJobTaskList();
        log.info("【LoaderExec.addExec】获取数据库待处理作业及任务查询时间：【{}】,查询个数【{}】",toDoManager.getLastQryTs(), addJobTaskList.size());
        this.dispatcherService.stopDispatcher();
        this.processorService.stopProcess();
        List<JobTask> newJobTaskList = new ArrayList<>();
        try {
            newJobTaskList = this.loaderService.mergeAddDispenseList(addJobTaskList);
            this.loaderService.mergeAddToDo(newJobTaskList);
        } catch (BizException e) {
            log.error("【LoaderExec.addDeal】增量加载异常异常：{}", e.getErrMsg(), e);
        } finally {
            log.debug("【LoaderExec.addDeal】增量数据合并处理结束【{}】", newJobTaskList.size());
        }
    }

    /**
     * 全量处理
     */
    private void allDeal() {
        log.debug("【LoaderExec.allDeal】获取数据库待处理队列--开始");
        List<JobTask> jobTaskList = this.loaderService.getAllJobTaskList();
        log.info("【LoaderExec.allDeal】获取数据库待处理队列--查询个数为【{}】", jobTaskList.size());
        this.dispatcherService.stopDispatcher();
        this.processorService.stopProcess();
        try {
            jobTaskList = this.loaderService.mergeDispenseList(jobTaskList);
            toDoManager.addJobList(jobTaskList);
            this.loaderService.mergeDeltaToDo();
        } catch (BizException e) {
            log.error("【LoaderExec.allDeal】全量加载异常：{}", e.getErrMsg(), e);
        } finally {
            log.debug("【LoaderExec.allDeal】全量处理结束《=======【{}】", jobTaskList.size());
        }
    }
}
